package server.main;

import DB.DBconnection;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import DAO.*;
import com.google.gson.Gson;
import model.*;
import server.utils.*;

public  class server_main {
        public static List<MessageForward> connSocketList = new ArrayList<>();
        public static DBconnection db = new DBconnection();
        public static List<Integer>  onlineUsers = new ArrayList<>();       //保存所有登录用户的账号
        private static final Logger logger = Logger.getLogger(server_main.class.getName()); // 日志库
        //启动服务器
        public void ServerStart()throws Exception {
            //InetAddress serverIP = InetAddress.getLocalHost();
            db.connect();
            int serverPort = 12345;
            ServerSocket serverSocket = new ServerSocket(serverPort);
            System.out.println("Sever is waiting for connection...");
            
            
            // 设置日志级别
            logger.setLevel(Level.INFO);
            // 创建一个文件处理器
            try {
            	String path = "." + File.separator + "log" + File.separator + "serverMain.log"; //   ./log/xxx.log
                FileHandler fileHandler = new FileHandler(path);
                fileHandler.setLevel(Level.INFO);

                // 创建一个日志格式化器
                Formatter formatter = new SimpleFormatter();
                fileHandler.setFormatter(formatter);

                // 将处理器添加到日志记录器
                logger.addHandler(fileHandler);
            } catch (IOException e) {
                e.printStackTrace();
            }

            while(true) {
                InetAddress localhost = InetAddress.getLocalHost();
                String ipAddress = localhost.getHostAddress();
                System.out.println("IP Address: " + ipAddress);
                logger.info("IP Address: " + ipAddress);
                
                Socket connSocket = serverSocket.accept();
                System.out.println("有一个新的连接");
                logger.info("有一个新的连接");
                DataInputStream input = new DataInputStream(connSocket.getInputStream());
                String json = input.readUTF();
                Gson gson = new Gson();
                Message mes = gson.fromJson(json, Message.class);
                System.out.println("type:" + mes.getType());
                
                if(mes.getType() == MsgType.LOGIN) {
                	System.out.println("有用户登录");
                	logger.info("有用户登录");
                	int uname = mes.getUserID();
                	String pwd = mes.getText();
                	LoginChecker check = new LoginChecker();
                	Message retmes = check.check(uname, pwd);
                	

                	DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
                	json = gson.toJson(retmes);
                	output.writeUTF(json);  
                	
                	
                	if(retmes.getType() == MsgType.LOGIN_SUCCEED) {
                		System.out.println("登录成功");
                		logger.info("登录成功");
                		onlineUsers.add(mes.getUserID());    //将新上线的用户的账户添加到列表
                		System.out.println("onlineUsers:" + onlineUsers);
                		logger.info("onlineUsers:" + onlineUsers);
                		connSocket.close();
               		    /*MessageForward messageForward = new MessageForward(input,output,retmes.getUserID());
                        Thread t = new Thread(messageForward);
                        t.start();
                        connSocketList.add(messageForward);*/
               	    }
                	                	            	                	
                }
                
                if(mes.getType() == MsgType.FRIENDLIST_UPDATER) {
                	System.out.println("连接成功");
                	logger.info("连接成功");
                	UpdateInformer u= new UpdateInformer(mes.getUserID(),connSocket);     //给客户端分配一个更新列表通知器
                	UpdateInformManager.addUpdateInformer(mes.getUserID(), u);            //初始化UpdateInformer的同时也会通知其好友进行更新 
                	u.sendAddMessage(mes.getUserID());
                //	System.out.println("申请消息成功发送给申请对象");
                	// System.out.println("申请消息成功发送给申请对象");
                }
                
                //客户端的下线通知
                if(mes.getType() == MsgType.UNLOAD_LOGIN) {
                	int useraccount = mes.getUserID();
                	System.out.println(useraccount);
                	Integer Useraccount = new Integer(useraccount);
                	boolean flag = onlineUsers.remove(Useraccount);
                	
                	if(flag) {
                		UpdateInformer u = UpdateInformManager.getUpdateInformer(useraccount);
                    	u.capsulateMessage(useraccount);
                    	System.out.println("通知成功");
                    	logger.info("通知成功");
                    	System.out.println("onlineusers: "+ onlineUsers);
                    	logger.info("onlineusers: "+ onlineUsers);
                	}                	
                }
                
             // 历史消息，接下来是消息转发，开多线程
                if(mes.getType() == MsgType.HISTORY_MESSAGE) {
                	logger.info(mes.getUserID() + "在房间" + mes.getRoomID() + "请求历史信息");
                	System.out.println(mes.getUserID() + "在房间" + mes.getRoomID() + "请求历史信息");
                	Vector<model.Message> history = new GetHistory(mes.getRoomID(), 0).getHistory();
                	DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
                	json = gson.toJson(history);
                	output.writeUTF(json);  
                	System.out.println("成功发送历史信息");
                	logger.info("成功发送历史信息");
                	// 准备消息转发
                	MessageForward messageForward = new MessageForward(connSocket, input,output,mes.getUserID());
                    Thread t = new Thread(messageForward);
                    t.start();
                    connSocketList.add(messageForward);
                }
                
                
                //向客户端返回新窗口的有关信息
                if(mes.getType() == MsgType.NEWCHAT) {
                	RoomDao roomDao = new RoomDao(db.con);
                	UserDao userDao = new UserDao(db.con);
                	
                	int roomid = -1;
                	roomid = roomDao.getIdByLongAccount(Long.parseLong(mes.getText()));
                	
                	//还是-1说明无法直接通过传过来的roomaccount找到房间，说明传过来的是好友聊天而不是群聊
                	if(roomid == -1) {
                		String roomaccount1 = mes.getTime()+mes.getText();           //好友聊天account的命名方式是两个人的account结合
                		String roomaccount2 = mes.getText()+mes.getTime();           //结合的方式可能是1或者2
                		
                		roomid = roomDao.getIdByLongAccount(Long.parseLong(roomaccount1));
                		if(roomid == -1) {
                			roomid = roomDao.getIdByLongAccount(Long.parseLong(roomaccount2));
                		}
                	}
                	
                	Vector<Integer> users_id = roomDao.getAllUser(roomid);
                	Vector<String> users_name = new Vector<String>();
                	
                	for(Integer i : users_id) {
                		String user_name = userDao.getUserNameById(i);
                		users_name.add(user_name);
                	}
                	
                	Message retmes = new Message();
                	String json_ids = gson.toJson(users_id);
                	String json_names = gson.toJson(users_name);
                	retmes.setText(json_ids);             //复用text传输users_id
                	retmes.setRooms(json_names);          //复用rooms传输users_name
                	retmes.setType(MsgType.RET_NEWCHATINFO);
                	retmes.setRoomID(roomid);
                	
                	String jsonString = gson.toJson(retmes);
                	DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
                	output.writeUTF(jsonString);
                	output.close();
                	System.out.println("成功发送窗口信息");
                	logger.info("成功发送窗口信息");
                }
                
                // 聊天机器窗口获取历史信息
                if(mes.getType() == MsgType.MACHINE_HISTORY) {
                	System.out.println(mes.getUserID() + "在聊天机器人房间请求历史信息");
                	logger.info(mes.getUserID() + "在聊天机器人房间请求历史信息");
                	GetHistory g = new GetHistory(0, mes.getUserID());
                	Vector<model.Message> history = g.getMachineHistory();
                	DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
                	json = gson.toJson(history);
                	output.writeUTF(json);  
                	logger.info(mes.getUserID() + "在聊天机器人房间成功获得历史信息");
                }
                
                // 聊天机器窗口插入信息
                if(mes.getType() == MsgType.MACHINE_MESSAGE) {
                	System.out.println(mes.getUserID() + "在聊天机器人房间插入历史信息");
                	logger.info(mes.getUserID() + "在聊天机器人房间插入信息");
                	new GetHistory(0, mes.getUserID()).insertMachineMessage(mes.getUserID(), mes.getRoomID(), mes.getText());
                }
                //处理用户注册
                if(mes.getType() == MsgType.REGISTER) {
                	UserDao userDao = new UserDao(db.con);
                	int account = userDao.createUser(mes.getTime(), mes.getText());
                	onlineUsers.add(account);
                	Message retmes = new Message();
                	retmes.setType(MsgType.REG_SUCCEED);
                	retmes.setUserID(account);          //复用userid属性来传输用户账号
                	json = gson.toJson(retmes);
                	DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
                	output.writeUTF(json);
                	output.close();
                	
               /* 	UpdateInformer u = UpdateInformManager.getUpdateInformer(account);
                	u.selfNotify(account);  */
                }
                
                
                //处理用户添加好友
                if(mes.getType() == MsgType.ADD_FRIEND) {
                	System.out.println("成功接收");
                	logger.info("成功接收");
                	String senderaccount = mes.getStates();
                	String receiveraccount = mes.getText();
                	String sendername = mes.getTime();
                	
                	MessageDAO messageDAO = new MessageDAO(db.con);
                	String result = messageDAO.createFriendReq(Integer.parseInt(senderaccount), sendername, Integer.parseInt(receiveraccount));
                	
                	System.out.println("result:"+result);
                	if(result == "ok") {
                		System.out.println("申请消息成功插入数据库");
                		logger.info("申请消息成功插入数据库");
                	}
                	
                	Message retmes = new Message();
                	retmes.setType(MsgType.ADD_RECEIVED);
                	DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
            		json = gson.toJson(retmes);
            		output.writeUTF(json);
            		output.close();
            		connSocket.close();
                	
                	if(onlineUsers.contains(Integer.parseInt(receiveraccount))) {
                		UpdateInformer u = UpdateInformManager.getUpdateInformer(Integer.parseInt(receiveraccount));
                		u.sendAddMessage(Integer.parseInt(receiveraccount));
                		System.out.println("申请消息成功发送给申请对象");
                		logger.info("申请消息成功发送给申请对象");
                	}
                }
                
                
                //用户同意添加好友
                if(mes.getType() == MsgType.ADD_ACCEPTED) {
                	UserDao userDao = new UserDao(db.con);
                	TotalDao totalDao = new TotalDao(db.con);
                	MessageDAO messageDAO = new MessageDAO(db.con);
                	int accept_account = mes.getUserID();
                	int req_account = mes.getRoomID();
                	String req_name = mes.getText();
                	String accept_name = userDao.getUserName(accept_account);
                	
                	boolean result1 = totalDao.addFriend(accept_account, req_account, req_name, accept_name);
                	String result2 = messageDAO.deleteFriendReq(req_account, req_name, accept_account);
                	
                	System.out.println("result1 :"+result1);
                	System.out.println("result2 :"+result2);
                	if(result1 && result2.equals("ok")) {               		
                		System.out.println("添加好友成功！");
                		logger.info("添加好友成功！");
                		
                		//通知接受者的所有好友更新好友列表，其实就是通知申请者更新好友列表
                	/*	if(onlineUsers.contains(accept_account)) {
                			System.out.println("成功通知申请者");
                			UpdateInformer u = UpdateInformManager.getUpdateInformer(accept_account);
                			u.capsulateMessage(accept_account);
                		}
                		
                		//通知申请者的所有好友更新好友列表，其实就是通知接收者更新好友列表
                		if(onlineUsers.contains(req_account)) {
                			System.out.println("成功通知接收者");
                			UpdateInformer u = UpdateInformManager.getUpdateInformer(req_account);
                			u.capsulateMessage(req_account);
                		}*/
                		UpdateInformer u = UpdateInformManager.getUpdateInformer(accept_account);
            			u.selfNotify(accept_account);
            			UpdateInformer u2 = UpdateInformManager.getUpdateInformer(req_account);
            			u2.selfNotify(req_account);
                	}
                	                	
                }
                
                //用户拒绝添加好友
                if(mes.getType() == MsgType.ADD_REJECTED) {
                	int accept_account = mes.getUserID();
                	int req_account = mes.getRoomID();
                	String req_name = mes.getText();
                	MessageDAO messageDAO = new MessageDAO(db.con);
                	String result = messageDAO.deleteFriendReq(req_account, req_name, accept_account);
                	
                	if(result.equals("ok")) {
                		System.out.println("成功拒绝！");
                		logger.info("成功拒绝！");
                	}
                }
                
                //用户申请删除好友
                if(mes.getType() == MsgType.DELETE_FRIEND) {
                	int maccount = mes.getUserID();
                	int faccount = mes.getRoomID();
                	TotalDao totalDao = new TotalDao(db.con);
                	
                	boolean result = totalDao.deleFriend(maccount, faccount);
                	if(result) {
                		UpdateInformer u = UpdateInformManager.getUpdateInformer(maccount);
                		u.selfNotify(faccount);                     //复用selfnotify来通知已被删除的好友更新列表
                		System.out.println("成功删除好友");
                		logger.info("成功删除好友");
                	}else {
                		System.out.println("删除失败");
                		logger.info("删除失败");
					}
                }
                
                //用户申请退出群聊
                if(mes.getType() == MsgType.EXIT_GROUP) {
                	int maccount = mes.getUserID();
                	int roomaccount = mes.getRoomID();
                	Long roomAccount = new Long(roomaccount);
                	TotalDao totalDao = new TotalDao(db.con);
                	
                	boolean result = totalDao.exitGroup(maccount, roomAccount);
                	if(result) {
                		UpdateInformer u = UpdateInformManager.getUpdateInformer(maccount);
                		u.selfNotify(maccount);
                		System.out.println("成功退出群聊");
                		logger.info("成功退出群聊");
                	}else {
                		System.out.println("退出群聊失败");
                		logger.info("退出群聊失败");
                	}
                }
                
                //用户申请加入群聊
                if(mes.getType() == MsgType.ADD_GROUP) {
                	String req_account = mes.getStates();
                	String room_account = mes.getText();
                	RoomDao roomDao = new RoomDao(db.con);
                	UserDao userDao = new UserDao(db.con);
                	
                	int user_id = userDao.getUserId(Integer.parseInt(req_account));
                	int room_id = roomDao.getIdByLongAccount(Long.parseLong(room_account));
                	int result = roomDao.joinNewRoomByAccount(user_id, Integer.parseInt(room_account));
                	
                	if(result == 0) {
                		
                		int result2 = userDao.joinNewRoom(user_id, room_id);
                		if(result2 == 0){
                			Message retmes = new Message();
                        	retmes.setType(MsgType.ADD_RECEIVED);
                        	DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
                    		json = gson.toJson(retmes);
                    		output.writeUTF(json);
                    		output.close();
                    		connSocket.close();
                    		
                    		UpdateInformer u = UpdateInformManager.getUpdateInformer(Integer.parseInt(req_account));
                    		u.selfNotify(Integer.parseInt(req_account));
                   		                    		                   		
                    		System.out.println("成功加入群聊");
                    		logger.info("成功加入群聊");
                		}
                		
                	}else if(result == -2){
                		Message retmes = new Message();
                		retmes.setType(MsgType.GROUP_FULL);
                		DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
                		json = gson.toJson(retmes);
                		output.writeUTF(json);
                		output.close();
                		connSocket.close();
                	}
                }
                
                //用户从隐身切换为在线
                if(mes.getType() == MsgType.USER_ONLINE) {
                	int account = mes.getUserID();
                	onlineUsers.add(account);
                	UpdateInformer u = UpdateInformManager.getUpdateInformer(account);
                	u.capsulateMessage(account);
                	connSocket.close();
                }
                
                //用户从在线切换为隐身
                if(mes.getType() == MsgType.USER_HIDE) {
                	int account = mes.getUserID();
                	Integer Useraccount = new Integer(account);
                	boolean flag = onlineUsers.remove(Useraccount);
                	
                	if(flag) {
                		UpdateInformer u = UpdateInformManager.getUpdateInformer(account);
                    	u.capsulateMessage(account);                    	
                	}                	
                }
                
                //用户修改用户名
                if(mes.getType() == MsgType.NAME_MODIFY) {
                	int account = mes.getUserID();
                	String name = mes.getText();
                	UserDao userDao = new UserDao(db.con);
                	MessageDAO messageDAO = new MessageDAO(db.con);
                	
                	boolean result = userDao.modifyName(account, name);
                	boolean result2 = messageDAO.modifyName(account, name);
                	
                	if(result && result2) {
                		UpdateInformer u = UpdateInformManager.getUpdateInformer(account);
                		u.capsulateMessage(account);
                		System.out.println("成功修改用户名");
                		logger.info("成功修改用户名");
                	}else {
                		System.out.println("用户名修改失败");
                		logger.info("用户名修改失败");
                	}
                }
                
                //用户修改密码
                if(mes.getType() == MsgType.PWD_MODIFY) {
                	int account = mes.getUserID();
                	String pwd = mes.getText();
                	UserDao userDao = new UserDao(db.con);
                	
                	boolean result = userDao.modifyPwd(account, pwd);
                	
                	if(result) {                		                		
                		System.out.println("成功修改密码");
                		logger.info("成功修改密码");
                	}else {
                		System.out.println("密码修改失败");
                		logger.info("密码修改失败");
                	}
                }
            }
                      
            // serverSocket.close();
		}  
	}	
